package jaux.tank.admin.modular.system.controller;

import java.util.List;
import java.util.Optional;

import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.HttpClientErrorException;

import com.google.code.kaptcha.Constants;

import jaux.tank.admin.config.properties.TankProperties;
import jaux.tank.admin.core.base.controller.BaseController;
import jaux.tank.admin.core.util.ApiMenuFilter;
import jaux.tank.admin.core.util.KaptchaUtil;
import jaux.tank.bean.core.ShiroUser;
import jaux.tank.bean.entity.system.User;
import jaux.tank.bean.exception.InvalidKaptchaException;
import jaux.tank.bean.exception.ValidException;
import jaux.tank.bean.vo.front.Rets;
import jaux.tank.bean.vo.node.MenuNode;
import jaux.tank.dao.cache.LoginIdCache;
import jaux.tank.dao.system.MenuRepository;
import jaux.tank.dao.system.UserRepository;
import jaux.tank.platform.log.LogManager;
import jaux.tank.platform.log.LogTaskFactory;
import jaux.tank.service.system.MenuService;
import jaux.tank.shiro.ShiroKit;
import jaux.tank.utils.CryptUtils;
import jaux.tank.utils.HttpKit;
import jaux.tank.utils.ObjectId;
import jaux.tank.utils.ToolUtil;

/**
 * 登录控制器
 *
 * @Date 2017年1月10日 下午8:25:24
 */
@Controller
public class LoginController extends BaseController {
    Logger logger = LoggerFactory.getLogger(LoginController.class);
    @Autowired
    MenuRepository menuRepository;
    @Autowired
    MenuService menuService;
    @Autowired
    UserRepository userRepository;
    @Autowired
    LoginIdCache loginIdCache;
    @Autowired
    TankProperties tankProps;

    /**
     * 跳转到主页
     */
    @GetMapping("/")
    public String index(Model model) {
        //获取菜单列表
        Optional<ShiroUser> user = ShiroKit.getUser();
		List<String> roleList = user.isPresent()?user.get().getRoleList():null;
        if (roleList == null || roleList.isEmpty()) {
            ShiroKit.getSubject().logout();
            model.addAttribute("tips", "该用户没有角色，无法登陆");
            return TankProperties.LOGIN_VIEW;
        }


            List<MenuNode> menuNodes =  menuService.getMenusByRoleIds(roleList);
            List<MenuNode> titles = MenuNode.buildTitle(menuNodes);
            titles = ApiMenuFilter.build(titles);

            model.addAttribute("titles", titles);


        //获取用户头像
        String id = user.get().getId();
        Optional<User> userOpt = userRepository.findById(id);
        if(userOpt.isPresent()) {
        	
        	model.addAttribute("avatar", userOpt.get().getAvatar());
        }

        return "/index.html";
    }

    /**
     * 跳转到登录页面
     */
    @GetMapping("/login")
    public String login() {
        if (ShiroKit.isAuthenticated() || ShiroKit.getUser().isPresent()) {
            return REDIRECT + "/";
        } else {
            return TankProperties.LOGIN_VIEW;
        }
    }

    /**
     * 点击登录执行的动作
     */
    @PostMapping("/login")
    public String loginVali(@RequestParam("username") String username,
    		@RequestParam("password") String password,
    		@RequestParam(name="remember", defaultValue="off") String remember,
    		@RequestParam(name="kaptcha", required=false) String kaptcha,
    		@RequestParam(name = "loginId", required = false) String loginId
    		) {
    	// 删除登录id
    	boolean loginIdAvaliable = false;
    	if(loginId !=null) {
    		loginIdAvaliable = loginIdCache.get(loginId);
    		loginIdCache.remove(loginId);
    	}
    	// 是否开启本地登录
    	if(!tankProps.isLocalLogin()) {
    		throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
    	}
    	// 是否开启验证登录会话有效性
    	if((tankProps.isLoginPasswdEncrypted()||tankProps.isValidLoginId()) && !loginIdAvaliable) {
    		throw new InvalidSessionException("登录会话无效");
    	}
    	// 判断是否开启了登录密码加密
    	if(tankProps.isLoginPasswdEncrypted()) {
    		password = CryptUtils.decode(password, loginId);
    	}

        //验证验证码是否正确
        if (Boolean.TRUE.equals(KaptchaUtil.getKaptchaOnOff())) {
//              kaptcha = super.getPara("kaptcha").trim();
            String code = (String) super.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
            if (ToolUtil.isEmpty(kaptcha) || !kaptcha.equalsIgnoreCase(code)) {
                throw new InvalidKaptchaException();
            }
        }

        Subject currentUser = ShiroKit.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray());

        token.setRememberMe("on".equalsIgnoreCase(remember));

        currentUser.login(token);

        Optional<ShiroUser> shiroUser = ShiroKit.getUser();
        super.getSession().setAttribute("shiroUser", shiroUser.orElse(null));
        super.getSession().setAttribute("username", shiroUser.isPresent()?shiroUser.get().getAccount():"");
        super.getSession().setAttribute("loginPath", HttpKit.getRequest().getRequestURI());
        super.getSession().setAttribute("userAgent", HttpKit.getUserAgent());

        LogManager.me().executeLog(LogTaskFactory.loginLogWithUserAgent(shiroUser.isPresent()?shiroUser.get().getId():"", HttpKit.getIp(), HttpKit.getUserAgent()));

        ShiroKit.getSession().setAttribute("sessionFlag", true);

        return REDIRECT + "/";
    }

    /**
     * 退出登录
     */
    @GetMapping("/logout")
    public String logOut() {
        Optional<ShiroUser> user = ShiroKit.getUser();
		LogManager.me().executeLog(LogTaskFactory.exitLog(user.isPresent()?user.get().getId():"", HttpKit.getIp()));
        ShiroKit.getSubject().logout();
        return REDIRECT + "/login";
    }
}
